package com.easyJava.builder;

import com.easyJava.bean.Constants;
import com.easyJava.bean.FieldInfo;
import com.easyJava.bean.TableInfo;
import com.easyJava.utils.BufferedWriterUtils;
import com.easyJava.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;

@Slf4j
public class BuildPO {
    public static void execute(TableInfo tableInfo){
        File folder = new File(Constants.PATH_PO);
        folder.mkdirs();

        File file = new File(folder, tableInfo.getBeanName() + Constants.FILE_SUFFIX_JAVA);

        try (
            OutputStream out = new FileOutputStream(file);
            OutputStreamWriter ow = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            BufferedWriter bufferedWriter = new BufferedWriter(ow);
        ){
            BufferedWriterUtils bw = new BufferedWriterUtils(bufferedWriter);
            //引包
            bw.write("package " + Constants.PACKAGE_PO + ";");
            bw.newLine();

            //根据需要导入时间和浮点数类
            importRequirePackage(tableInfo, bw);

            //导入序列化接口
            bw.write("import java.io.Serializable;");
            bw.newLine();

            //生成注释
            BuildComment.createClassComment(bw, tableInfo.getComment());
            //PO类
            bw.write("public class " + tableInfo.getBeanName() + " implements Serializable{");

            //生成属性
            generateField(tableInfo, bw);

            //生成getter setter方法
            generateSetAndGet(tableInfo, bw);

            //生成toString方法
            generateToString(tableInfo, bw);

            bw.write("}");
            bw.flush();
        }catch (Exception e){
            log.error("创建po失败:{}", e);
        }


    }

    private static void generateToString(TableInfo tableInfo, BufferedWriterUtils bw) throws IOException {
        StringBuffer sb = new StringBuffer();
        for (FieldInfo fieldInfo : tableInfo.getFieldList()){
            if(StringUtils.isEmpty(fieldInfo.getComment())) continue;
            String fieldExpression = fieldInfo.getBeanFieldName();
            if(ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPE, fieldInfo.getSqlType())){
                fieldExpression = "LocalDateTimeUtils.format(LocalDateTimeUtils.YYYY_MM_DD_HH_MM_SS, " + fieldInfo.getBeanFieldName() + ")";
            }
            if(ArrayUtils.contains(Constants.SQL_DATE_TYPE, fieldInfo.getSqlType())){
                fieldExpression = "LocalDateUtils.format(LocalDateUtils.YYYY_MM_DD, " + fieldInfo.getBeanFieldName() + ")";
            }
            sb.append("\"" + fieldInfo.getComment() + ":\"  + (" + fieldInfo.getBeanFieldName() + " == null ? \"空\" : " + fieldExpression + ") + \"\\n\" + ");
        }
        String toString = sb.substring(0, sb.lastIndexOf("+")-1);

        bw.write("\t@Override");
        bw.write("\tpublic String toString(){");
        bw.write("\t\treturn " + toString + ";");
        bw.write("\t}");
    }

    private static void generateSetAndGet(TableInfo tableInfo, BufferedWriterUtils bw) throws IOException {
        for(FieldInfo fieldInfo : tableInfo.getFieldList()){
            bw.write("\tpublic void set" + StringUtils.upperFirstChar(fieldInfo.getBeanFieldName()) + "(" + fieldInfo.getJavaType() + " " + fieldInfo.getBeanFieldName() + "){");
            bw.write("\t\tthis." + fieldInfo.getBeanFieldName() + " = " + fieldInfo.getBeanFieldName() + ";");
            bw.write("\t}");
            bw.newLine();

            bw.write("\tpublic " + fieldInfo.getJavaType() + " get" + StringUtils.upperFirstChar(fieldInfo.getBeanFieldName()) + "(){");
            bw.write("\t\treturn this." + fieldInfo.getBeanFieldName() + ";");
            bw.write("\t}");
            bw.newLine();
        }
    }

    private static void generateField(TableInfo tableInfo, BufferedWriterUtils bw) throws IOException {
        for(FieldInfo fieldInfo : tableInfo.getFieldList()){
            BuildComment.createFieldComment(bw, fieldInfo.getComment());
            BuildAnnotation.createFieldAnnotation(bw, fieldInfo);
            bw.write("\tprivate " + fieldInfo.getJavaType() + " " + fieldInfo.getBeanFieldName() + ";");
            bw.newLine();
        }
    }

    private static void importRequirePackage(TableInfo tableInfo, BufferedWriterUtils bw) throws IOException {
        if(tableInfo.isHaveDate()){
            bw.write("import java.time.LocalDate;");
            bw.write("import " + Constants.PACKAGE_UTILS + ".LocalDateUtils;");
            bw.write(Constants.DATE_FORMAT_PACKAGE);
            bw.write(Constants.DATE_JSON_FORMAT_PACKAGE);
        }
        if(tableInfo.isHaveDateTime()){
            bw.write("import java.time.LocalDateTime;");
            bw.write("import " + Constants.PACKAGE_UTILS + ".LocalDateTimeUtils;");
            bw.write(Constants.DATE_FORMAT_PACKAGE);
            bw.write(Constants.DATE_JSON_FORMAT_PACKAGE);
        }
        if(tableInfo.isHaveBigDecimal()){
            bw.write("import java.math.BigDecimal;");
        }
        if(tableInfo.isHaveIgnoreField()){
            bw.write(Constants.IGNORE_FIELD_PACKAGE);
        }
    }
}
